package main

import (
	"ccmouse/retriever/downloader/mock"
	"ccmouse/retriever/downloader/real"
	"fmt"
	"time"
)

type Retriever interface {
	Get(url string) string
}

type Poster interface {
	Post(url string, form map[string]interface{}) string
}

type RetrieverPoster interface {
	Retriever
	Poster
}

func download(r Retriever) string {
	return r.Get("https://www.baidu.com")
}

func post(p Poster) string {
	return p.Post("https://www.jd.com", map[string]interface{}{
		"username": "un",
		"password": "pwd",
	})
}

const url = "https://www.taobao.com"

func session(rp RetrieverPoster) string {
	rp.Post(url, map[string]interface{}{
		"contents": "another fake contents",
	})

	return rp.Get(url)
}

func main() {
	var r Retriever
	r = &mock.Retriever{Contents: "this is a fake retriever"}
	inspect(r)
	r = &real.Retriever{UserAgent: "Mozilla/5.0", TimeOut: time.Second}
	inspect(r)
	//fmt.Println(download(r))

	fmt.Println("Type Assertion: ")
	if m, ok := r.(*mock.Retriever); ok {
		fmt.Println("m is *mock.Retriever and" +
			" triangle complete: " + m.Contents)
	}

	if r, ok := r.(*real.Retriever); ok {
		fmt.Println("r is *real.Retriever and" +
			" triangle complete: " + r.UserAgent)
	}

	fmt.Println("==============Combine============")
	var rp RetrieverPoster = &mock.Retriever{
		Contents: "this is a fake retriever",
	}
	fmt.Println(session(rp))

}

func inspect(r Retriever) {
	fmt.Printf("Type = %T, Value = %v\n",
		r, r)
	fmt.Println("Type Switch:")
	switch v := r.(type) {
	case *mock.Retriever:
		fmt.Printf(" > r.Contents = %s\n", v.Contents)
	case *real.Retriever:
		fmt.Printf(" > r.UserAgent = %s, r.TimeOut = %v\n",
			v.UserAgent, v.TimeOut)
	default:
		fmt.Println("unknown type")
	}
}
